from logging import getLogger

from zope.interface import implements

from lxml import etree

from meercat.base.metadata import Metadata
from meercat.server.rest import interfaces



log = getLogger('meercat.server.rest.mapreduce.reducer')

class Reducer(object):
    implements(interfaces.IWebReducer)
    
    def __init__(self, formats=('web',), processors=[]):
        self.formats = formats
        self.processors = processors
    
    def getFormats(self):
        return self.formats
    
    def reduce(self, *metadata):
        log.debug('%s.reduce(%s)' % (str(self),str(metadata)))
        root = etree.Element('resource')
        format = ''
        
        if len(metadata) > 0:
            format = metadata[0].getFormat()
        
        data = {}
        
        for m in metadata:
            m = etree.fromstring(m.getValue())
            for child in m.xpath('//resource/*'):
                if child.get('id') and child.get('source'):
                    key = (child.get('source'),child.get('id'))
                else:
                    key = ('','')
                
                data.setdefault(child.tag,{}).setdefault(key,[]).append(child)
        
        for p in self.processors:
            p(data)
        
        for tag, keyed_values in data.iteritems():
            for key, values in keyed_values.iteritems():
                source, id = key
                summary = etree.Element(tag)
                if id:
                    summary.set('id',id)
                if source:
                    summary.set('source', source)
                
                for child in values:
                    map(summary.append, child.getchildren())
                
                root.append(summary)
        
        del data
        
        output_value = etree.tostring(root,
                                      encoding='utf-8').replace('\n','').strip()
        
        del root
        
        return Metadata(source=u'meercat.server.rest.reducer.Reducer',
                        format=format,
                        value=output_value)
